from events import *
import pygame
import preferences
from pygame.locals import *

vectorSum = lambda a,b: (a[0]+b[0], a[1]+b[1])


#------------------------------------------------------------------------------
class Widget(pygame.sprite.Sprite):
	def __init__(self, evManager, container=None):
		pygame.sprite.Sprite.__init__(self)

		self.evManager = evManager
		self.evManager.RegisterListener( self )

		self.container = container
		self.focused = 0
		self.dirty = 1

	#----------------------------------------------------------------------
	def SetFocus(self, val):
		self.focused = val
		self.dirty = 1

	#----------------------------------------------------------------------
 	def kill(self):
		self.container = None
		del self.container
		pygame.sprite.Sprite.kill(self)

	#----------------------------------------------------------------------
 	def Notify(self, event):
		if isinstance( event, GUIFocusThisWidgetEvent ) \
		  and event.widget is self:
			self.SetFocus(1)

		elif isinstance( event, GUIFocusThisWidgetEvent ) \
		  and self.focused:
			self.SetFocus(0)



#------------------------------------------------------------------------------
class LabelSprite(Widget):
	def __init__(self, evManager, text, container=None, fontSize=18, fontColor=(200,200,200), fontFamily=None):
		Widget.__init__( self, evManager, container)

		self.color = fontColor
		self.font = pygame.font.Font(fontFamily, fontSize)
		self.__text = text
		self.image = self.font.render( self.__text, 1, self.color)
		self.rect  = self.image.get_rect()

	#----------------------------------------------------------------------
	def SetText(self, text):
		self.__text = text
		self.dirty = 1

	#----------------------------------------------------------------------
	def update(self):
		if not self.dirty:
			return

		self.image = self.font.render( self.__text, 1, self.color )
		self.dirty = 0

class ImageSprite(Widget):
	
	def __init__(self, evManager, imagePath='', container=None):
		Widget.__init__( self, evManager, container)
		self.image = pygame.image.load(imagePath)
		self.rect  = self.image.get_rect()
	
	def update(self):
		if not self.dirty:
			return
		self.dirty = 0


class ClickableImageSprite(ImageSprite): #versao experimental
	limite_minimo_alfa = 10  #limite minimo que a partir do qual se considera visivel

	def __init__(self, evManager, imagePath='', clickedPath='', container=None, event=None):
		ImageSprite.__init__(self, evManager, imagePath, container)
                self.clicked = clickedPath
                self.event = event

	def Click(self, pos):
		#o clique so pode ser efetuado se a imagem for visivel
		try:
			self.dirty = 1
			if self.image.get_at( (pos[0] - self.rect.left, pos[1] - self.rect.top) ) >= \
			   self.limite_minimo_alfa:
				self.image = pygame.image.load(self.clicked)
                                self.evManager.Post(self.event)

		except IndexError:
			pass # nao faca nada

	def Notify(self, event):
		if isinstance( event, GUIClickEvent ):
			self.Click(event.pos)

#------------------------------------------------------------------------------
class ButtonSprite(Widget):
	def __init__(self, evManager, text, container=None, onClickEvent=None, fontSize=30 ):
		Widget.__init__( self, evManager, container)

		self.font = pygame.font.Font('data/wareagle.ttf', fontSize)
		self.text = text
		self.image = self.font.render( self.text, 1, (255,0,0))
		self.rect  = self.image.get_rect()

		self.onClickEvent = onClickEvent

	#----------------------------------------------------------------------
	def update(self):
		if not self.dirty:
			return

		if self.focused:
			color = (255,0,0)
		else:
			color = (255,255,255)
		self.image = self.font.render( self.text, 1, color)
		#self.rect  = self.image.get_rect()

		self.dirty = 0

	#----------------------------------------------------------------------
	def Connect(self, eventDict):
		for key,event in eventDict.iteritems():
			try:
				self.__setattr__( key, event )
			except AttributeError:
				print "Couldn't connect the ", key
				pass


	#----------------------------------------------------------------------
	def Click(self):
		self.dirty = 1
		if self.onClickEvent:
			self.evManager.Post( self.onClickEvent )

	#----------------------------------------------------------------------
 	def Notify(self, event):
		if isinstance( event, GUIPressEvent ) and self.focused:
			self.Click()

		elif isinstance( event, GUIClickEvent ) \
		  and self.rect.collidepoint( event.pos ):
			self.Click()

		elif isinstance( event, GUIMouseMoveEvent ) \
		  and self.rect.collidepoint( event.pos ):
		  	ev = GUIFocusThisWidgetEvent(self)
			self.evManager.Post( ev )

		Widget.Notify(self,event)

			
#------------------------------------------------------------------------------
class TextBoxSprite(Widget):
	def __init__(self, evManager, width, container=None ):
		Widget.__init__( self, evManager, container)

		self.font = pygame.font.Font(None, 30)
		linesize = self.font.get_linesize()

		self.rect = pygame.Rect( (0,0,width, linesize + 4) )
		boxImg = pygame.Surface( self.rect.size )
		boxImg.fill((255,255,255))
		boxImg.convert_alpha()
		color = (0,0,0)
		pygame.draw.rect( boxImg, color, self.rect, 4 )

		self.emptyImg = boxImg.convert_alpha()
		self.image = boxImg

		self.text = ''
		self.textPos = (4, 4)

	#----------------------------------------------------------------------
	def update(self):
		if not self.dirty:
			return

		text = self.text
		if self.focused:
			text += '|'

		textColor = (0,0,0)
		textImg = self.font.render( text, 1, textColor )
		self.image.blit( self.emptyImg, (0,0) )
		self.image.blit( textImg, self.textPos )

		self.dirty = 0

	#----------------------------------------------------------------------
	def Click(self):
		self.focused = 1
		self.dirty = 1

	#----------------------------------------------------------------------
	def SetText(self, newText):
		self.text = newText
		self.dirty = 1

	#----------------------------------------------------------------------
 	def Notify(self, event):

		if isinstance( event, GUIPressEvent ) and self.focused:
			self.Click()

		elif isinstance( event, GUIClickEvent ) \
		  and self.rect.collidepoint( event.pos ):
			self.Click()

		elif isinstance( event, GUIClickEvent ) \
		  and self.focused:
			self.SetFocus(0)

		elif isinstance( event, GUIMouseMoveEvent ) \
		  and self.rect.collidepoint( event.pos ):
		  	ev = GUIFocusThisWidgetEvent(self)
			self.evManager.Post( ev )

		elif isinstance( event, GUIKeyEvent ) \
		  and self.focused:
		  	newText = self.text + event.key
			self.SetText( newText )

		elif isinstance( event, GUIControlKeyEvent ) \
		  and self.focused and event.key == K_BACKSPACE:
		  	#strip of last character
		  	newText = self.text[:( len(self.text) - 1 )]
			self.SetText( newText )

		Widget.Notify(self,event)


#------------------------------------------------------------------------------
class WidgetContainer:
	def __init__(self, evManager, rect):
		self.evManager = evManager
		self.evManager.RegisterListener( self )

		self.rect = rect

		self.widgets = [ ]

	#----------------------------------------------------------------------
 	def ArrangeWidgets(self, xPadding=20, yPadding=100):
		xOffset = self.rect.x
		yOffset = self.rect.y

		xStep = 1
		yStep = 1
		for wid in self.widgets:
			wid.rect.x = xOffset + (xPadding*xStep)
			wid.rect.y = yOffset + (yPadding*yStep)

			#Check to see if we didn't screw it up...
			if wid.rect.left > self.rect.right \
			  or wid.rect.top > self.rect.bottom:
				print wid, self
				print wid.rect, self.rect
				raise Exception( "Widget Outside Container")

			yStep += 1
			if yStep*yPadding > self.rect.height:
				yStep = 1
				xStep += 1

	#----------------------------------------------------------------------
 	def ChangeFocusedWidget(self, change):
		i = 0
		for wid in self.widgets:
			if wid.focused:
				break
			i += 1

		currentlyFocused = i
		changeToWidget = i + change

		#no widget was focused
		if currentlyFocused == len( self.widgets ):
			self.widgets[0].SetFocus(1)
			return

		#the desired index is out of range
		elif changeToWidget <= -1  \
		  or changeToWidget >= len( self.widgets ):
			changeToWidget = changeToWidget%len(self.widgets)

		self.widgets[currentlyFocused].SetFocus(0)
		self.widgets[changeToWidget].SetFocus(1)


	#----------------------------------------------------------------------
 	def Notify(self, event):

		if isinstance( event, GUIFocusNextWidgetEvent):
			self.ChangeFocusedWidget(1)

		elif isinstance( event, GUIFocusPrevWidgetEvent):
			self.ChangeFocusedWidget(-1)


	#----------------------------------------------------------------------
 	def kill(self):
		for sprite in self.widgets:
			sprite.kill()
		while len( self.widgets ) > 0:
			wid = self.widgets.pop()
			del wid
		del self.widgets

#------------------------------------------------------------------------------
class WidgetAndContainer( Widget, WidgetContainer ):
	#----------------------------------------------------------------------
	def __init__(self, evManager, container):
		Widget.__init__( self, evManager, container)

		self.widgets = [ ]

	#----------------------------------------------------------------------
 	def kill(self):
		WidgetContainer.kill(self)
		Widget.kill(self)


#------------------------------------------------------------------------------
class TextEntrySprite(WidgetAndContainer):
	def __init__(self, evManager, labelText, fontSize=18, fontColor=(200,200,200), fontFamily=None, container=None, distance=0 ):
		WidgetAndContainer.__init__( self, evManager, container)


		self.widgets = [ LabelSprite( evManager, labelText, container=self, fontSize=fontSize, fontColor=fontColor, fontFamily=fontFamily ),
		                 TextBoxSprite( evManager, 200, container=self ),
		               ]

		self.widgets[0].rect.width += distance

		width = self.widgets[0].rect.width \
		        + self.widgets[1].rect.width + 10
		height = self.widgets[1].rect.height

		self.image = pygame.Surface( (width, height), pygame.SRCALPHA, 32 )
		self.image.fill( (0,0,0,0) )
		#self.image.set_colorkey( (255,0,255) )

		self.background = self.image.convert_alpha()
		self.rect = self.image.get_rect()

	#----------------------------------------------------------------------
 	def ArrangeWidgets(self):
		xyOffset = ( self.rect.x, self.rect.y )
		self.widgets[0].rect.topleft = vectorSum( xyOffset, (0,0) ) 
		x = self.widgets[0].rect.width + 10
		self.widgets[1].rect.topleft = vectorSum( xyOffset, (x,0) ) 

	#----------------------------------------------------------------------
	def update(self):
		if not self.dirty:
			return

		self.ArrangeWidgets()

		self.image.blit( self.background, [0,0] )
		for wid in self.widgets:
			wid.update()
			destpos = [wid.rect.x - self.rect.x,
				   wid.rect.y - self.rect.y ]
			self.image.blit( wid.image, destpos )

		self.dirty = 0

	#----------------------------------------------------------------------
 	def Notify(self, event):

		#See if we're dirty
		for wid in self.widgets:
			if wid.dirty:
				self.dirty = 1
				break


#------------------------------------------------------------------------------
class ButtonColorSprite(Widget):
	def __init__(self, evManager, buttonColor, container=None, onClickEvent=None ):
		Widget.__init__( self, evManager, container)

		self.rect = pygame.Rect( (0,0,30,34) )
		boxImg = pygame.Surface( self.rect.size )
		boxImg.fill(buttonColor)
		boxImg.convert_alpha()
		color = (0,0,0)
		#note que essa utilizacao de preferences vai ser retirada
		#if buttonColor == preferences.gameColors[preferences.playerData['color']]:
		#	color = (255,255,255)

		pygame.draw.rect( boxImg, color, self.rect, 4 )

		self.emptyImg = boxImg.convert_alpha()
		self.image = boxImg

		self.onClickEvent = onClickEvent

	#----------------------------------------------------------------------
	def update(self):
		if not self.dirty:
			return
		pygame.draw.rect( self.image, (255,255,255), self.rect, 4 )
		self.dirty = 0

	#----------------------------------------------------------------------
	def Connect(self, eventDict):
		for key,event in eventDict.iteritems():
			try:
				self.__setattr__( key, event )
			except AttributeError:
				print "Couldn't connect the ", key
				pass

	#----------------------------------------------------------------------
	def SetPlayerColor(self):
		self.dirty = 1

	#----------------------------------------------------------------------
	def Click(self):
		self.dirty = 1
		self.focused = 1
		self.update()
		self.SetPlayerColor()
		if self.onClickEvent:
			self.evManager.Post( self.onClickEvent )

	#----------------------------------------------------------------------
 	def Notify(self, event):
		if isinstance( event, GUIPressEvent ) and self.focused:
			self.Click()

		elif isinstance( event, GUIClickEvent ) \
		  and self.rect.collidepoint( event.pos ):
			self.Click()

		elif isinstance( event, GUIMouseMoveEvent ) \
		  and self.rect.collidepoint( event.pos ):
		  	ev = GUIFocusThisWidgetEvent(self)
			self.evManager.Post( ev )

		Widget.Notify(self,event)


#------------------------------------------------------------------------------
class ColorEntrySprite(WidgetAndContainer):
	def __init__(self, evManager, labelText, buttonColor, fontSize=18, fontColor=(200,200,200), fontFamily=None, container=None, \
                        distance=0, onClickEvent=None):
		WidgetAndContainer.__init__( self, evManager, container)


		self.widgets = [ LabelSprite( evManager, labelText, container=self, fontSize=fontSize, fontColor=fontColor, fontFamily=fontFamily ),
		                 ButtonColorSprite( evManager, buttonColor, container=self, onClickEvent=onClickEvent ),
		               ]

		self.widgets[0].rect.width += distance

		width = self.widgets[0].rect.width \
		        + self.widgets[1].rect.width + 10
		height = self.widgets[1].rect.height

		self.image = pygame.Surface( (width, height), pygame.SRCALPHA, 32 )
		self.image.fill( (0,0,0,0) )
		#self.image.set_colorkey( (255,0,255) )

		self.background = self.image.convert_alpha()
		self.rect = self.image.get_rect()

	#----------------------------------------------------------------------
 	def ArrangeWidgets(self):
		xyOffset = ( self.rect.x, self.rect.y )
		self.widgets[0].rect.topleft = vectorSum( xyOffset, (0,0) ) 
		x = self.widgets[0].rect.width + 10
		self.widgets[1].rect.topleft = vectorSum( xyOffset, (x,0) ) 

	#----------------------------------------------------------------------
	def update(self):
		if not self.dirty:
			return

		self.ArrangeWidgets()

		self.image.blit( self.background, [0,0] )
		for wid in self.widgets:
			wid.update()
			destpos = [wid.rect.x - self.rect.x,
				   wid.rect.y - self.rect.y ]
			self.image.blit( wid.image, destpos )

		self.dirty = 0

	#----------------------------------------------------------------------
 	def Notify(self, event):

		#See if we're dirty
		for wid in self.widgets:
			if wid.dirty:
				self.dirty = 1
				break


if __name__ == "__main__":
	print "that was unexpected"
